function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }

function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

import React, { useRef, useState, useEffect } from 'react';
import { usePersistFn, useDebounceFn, useUpdateEffect } from 'ahooks';
import { Dropdown, Menu } from 'antd';
import { getLaneStyle, nextTick } from '../../tools';
import { getGraph, registerLane, registerNode, registerModuleNode, registerEdge, registerResizeNode, registerNodeMenuContext, registerResizeLane, registerEdgeRemove, registerNodeNumChange, registerAutoSave, registerHistory, registerLaneCellChange, registerKeyboard } from './tools';

const Lane = function Lane({
  data,
  onActions,
  onLoad,
  assets,
  setCurrentCell,
  zoom = 1,
  isFullScreen,
  setCanRedo,
  setCanUndo,
  onUndoOrRedo
}) {
  const containerRef = useRef(null);
  const laneRef = useRef(null);
  const laneTitleRef = useRef(null);
  const laneWrapperRef = useRef(null);
  const miniMapRef = useRef(null);
  const menuRef = useRef(null);

  const _useState = useState(),
        _useState2 = _slicedToArray(_useState, 2),
        graph = _useState2[0],
        setGraph = _useState2[1];

  useEffect(() => {
    if (!graph) return;
    const nodes = graph.model.getNodes();

    if (Array.isArray(nodes)) {
      nodes.forEach(n => {
        const _n$data = n.data,
              type = _n$data.type,
              image = _n$data.image;

        if (type === 'node') {
          n.attr('itemTag/xlinkHref', assets[image]);
        }
      });
    }
  }, [assets, graph]); // 画布事件响应

  const handlerActions = usePersistFn(action => {
    onActions && onActions(action);
    onVisibleChange(false);
  }); // 删除连接 防抖

  const _useDebounceFn = useDebounceFn(edge => {
    if (!edge.data) return;
    setCurrentCell(edge);
    nextTick(() => handlerActions('delete'));
  }, {
    wait: 100
  }),
        onRemoveEdge = _useDebounceFn.run;

  const syncLaneTitle = usePersistFn(() => {
    const x6Graph = containerRef.current;
    const laneTitleSvg = laneTitleRef.current;
    if (!x6Graph || !laneTitleSvg) return; // const x6GraphParent = x6Graph.parentNode;

    const x6GraphLaneShapes = x6Graph.querySelectorAll('g[data-shape="lane"]');
    const laneTitleStage = laneTitleSvg.querySelector('.x6-graph-svg-stage');
    laneTitleStage.innerHTML = '';
    Array.from(x6GraphLaneShapes).forEach(laneShapeNode => {
      const laneTitleLaneShape = laneShapeNode.cloneNode(true);
      Array.from(laneTitleLaneShape.childNodes).forEach(node => {
        const className = node.getAttribute('class');

        if (className === 'laneBody') {
          laneTitleLaneShape.removeChild(node);
        } else if (className === 'resizeBorder') {
          node.setAttribute('width', '30');
        }
      });
      laneTitleStage.appendChild(laneTitleLaneShape);
    });
    syncContainerSize();
    x6Graph.style.transformOrigin = 'left top';
    x6Graph.style.transform = `scale(${zoom})`;
    laneTitleSvg.style.transformOrigin = 'left top';
    laneTitleSvg.style.height = x6Graph.offsetHeight + 'px';
    laneTitleSvg.style.transform = `scale(${zoom})`;
  }); // 同步画布容器的尺寸

  const syncContainerSize = usePersistFn(() => {
    if (!graph || !laneWrapperRef.current || !containerRef.current) return;
    const laneNodeList = graph.getNodes().filter(node => node.shape === 'lane');
    const maxHeight = Math.max(laneWrapperRef.current.parentNode.clientHeight || 0, laneNodeList.reduce((p, item) => p + item.size().height, 0) + 50);
    containerRef.current.style.height = maxHeight + 'px';
    if (!containerRef.current.parentNode) return;
    containerRef.current.parentNode.style.height = containerRef.current.offsetHeight * zoom + 'px';
  }); // 监控缩放

  useEffect(() => {
    // 当数据发生变化时，需要等画布发生变化后再去同步节点才能准确
    nextTick(() => {
      const x6Graph = containerRef.current;
      if (!graph || !x6Graph) return;
      syncLaneTitle();
      const x6GraphParent = x6Graph.parentNode;
      if (!x6GraphParent) return;
      x6GraphParent.style.height = x6Graph.offsetHeight * zoom + 'px';
    });
  }, [zoom, graph, data]);

  const handleMenuClick = ({
    key
  }) => {
    handlerActions(key);
  }; // 改变泳道高度


  const onLaneReszie = usePersistFn((laneNode, width, height, minHeight) => {
    if (height < minHeight || !graph) return;else laneNode.size(width, height);
    const laneNodeList = graph.getNodes().filter(node => node.shape === 'lane');
    const laneIndex = laneNodeList.findIndex(lane => lane.id === laneNode.id);

    if (laneIndex > -1) {
      // 改变当前泳道的高度
      let currentY = laneNode.position().y + height; // 调整泳道内节点的Y坐标

      const children = laneNode.getChildren();

      if (Array.isArray(children) && children.length) {
        children.forEach(child => {
          const _child$size = child.size(),
                ch = _child$size.height;

          const _child$position = child.position(),
                cx = _child$position.x,
                cy = _child$position.y;

          if (cy + ch > currentY) {
            child.position(cx, currentY - ch);
          }
        });
      } // 调整位置在当前泳道下方的泳道的位置


      laneNodeList.slice(laneIndex + 1).forEach(nextLaneNode => {
        const _nextLaneNode$positio = nextLaneNode.position(),
              laneX = _nextLaneNode$positio.x,
              laneY = _nextLaneNode$positio.y;

        nextLaneNode.position(laneX, currentY); // 调整泳道位置的同时也要调整泳道内子节点的位置

        const children = nextLaneNode.getChildren();

        if (Array.isArray(children) && children.length > 0) {
          children.forEach(childNode => {
            const _childNode$position = childNode.position(),
                  childX = _childNode$position.x,
                  childY = _childNode$position.y;

            const offsetY = childY - laneY;
            childNode.position(childX, currentY + offsetY);
          });
        }

        currentY += nextLaneNode.size().height;
      });
    }
  }); // 添加连接

  const onAddLink = edge => {
    setCurrentCell(edge);
    nextTick(() => handlerActions('add'));
  };

  const initPage = usePersistFn(() => {
    if (!containerRef.current || !laneWrapperRef.current || !laneWrapperRef.current // !miniMapRef.current
    ) {
      return;
    }

    let gh = graph;

    if (!gh) {
      registerLane({
        width: containerRef.current.clientWidth,
        height: 200
      });
      registerNode();
      registerModuleNode();
      registerEdge();
      gh = getGraph(containerRef.current, miniMapRef.current, {
        onAddLink
      });
      registerNodeMenuContext(gh, menuRef, setCurrentCell);
      registerResizeNode(gh);
      registerResizeLane(gh, onLaneReszie);
      registerEdgeRemove(gh, onRemoveEdge);
      registerNodeNumChange(gh);
      registerAutoSave(gh);
      registerHistory(gh, {
        setCanRedo,
        setCanUndo,
        onUndoOrRedo
      });
      registerKeyboard(gh, onActions);
    } else {
      gh.clearCells();
    }

    const cells = [];
    const laneDataList = data.laneList,
          nodeDataList = data.nodeList,
          linkDataList = data.linkList,
          width = data.width,
          height = data.height; // 计算页面宽高，并将宽度赋值给泳道，并在泳道的上下留出一定的空间方便拖拽

    const maxWidth = Math.max(containerRef.current.clientWidth, width || 0);
    const maxHeight = Math.max(laneWrapperRef.current.parentNode.clientHeight, height || 0);
    containerRef.current.style.width = maxWidth + 'px';
    containerRef.current.style.height = maxHeight + 'px';
    laneDataList.forEach(item => {
      item.width = maxWidth;
      if (!item.attrs) item.attrs = getLaneStyle(Number(item.id) - 1);
    }); // 泳道map方便查找

    const laneMap = {}; // 泳道图形化

    laneDataList.forEach(item => {
      const lane = gh.createNode(item);
      registerLaneCellChange(lane, () => nextTick(() => syncLaneTitle()));
      cells.push(lane);
      laneMap[lane.id] = lane;
    }); // 节点图形化

    const nodeInLaneMap = {};
    nodeDataList.forEach(item => {
      const _ref = item.data || {},
            image = _ref.image,
            preId = _ref.preId,
            bgImage = _ref.bgImage;

      const node = gh.createNode(item);
      node.attr({
        itemTag: {
          xlinkHref: assets[image]
        },
        backgorund: {
          xlinkHref: assets[bgImage]
        }
      });
      cells.push(node);
      if (!nodeInLaneMap[preId]) nodeInLaneMap[preId] = [];
      nodeInLaneMap[preId].push(node);
    }); // 连线图形化

    linkDataList.forEach(item => {
      const link = gh.createEdge(item);
      cells.push(link);
    });
    gh.resetCells(cells);
    Object.keys(nodeInLaneMap).forEach(laneId => {
      const lane = laneMap[laneId];
      const nodeList = nodeInLaneMap[laneId];
      lane.setChildren(nodeList);
    });
    gh.positionRect({
      x: 0,
      y: 0,
      width: maxWidth,
      height: maxHeight
    }, 'top-left');
    setGraph(gh);
    onLoad(gh);
    syncLaneTitle();
    gh.cleanHistory();
  });
  useEffect(() => {
    initPage();
  }, [data]);
  useUpdateEffect(() => {
    setTimeout(() => {
      initPage();
    }, 500);
  }, [isFullScreen]);
  const menu = /*#__PURE__*/React.createElement(Menu, {
    onClick: handleMenuClick
  }, /*#__PURE__*/React.createElement(Menu.Item, {
    key: "edite"
  }, /*#__PURE__*/React.createElement("a", {
    rel: "noopener noreferrer"
  }, "\u7F16\u8F91")), /*#__PURE__*/React.createElement(Menu.Item, {
    key: "delete"
  }, /*#__PURE__*/React.createElement("a", {
    rel: "noopener noreferrer"
  }, "\u5220\u9664")));

  const onVisibleChange = visible => {
    if (!visible) {
      setTimeout(() => {
        if (!menuRef.current) return;
        menuRef.current.style.left = '-100px';
        menuRef.current.style.top = '-100px';
      }, 100);
    }
  };

  return /*#__PURE__*/React.createElement("div", {
    className: "ra-arch-laneWrapper",
    ref: laneWrapperRef
  }, /*#__PURE__*/React.createElement(Dropdown, {
    overlay: menu,
    placement: "bottomLeft",
    onVisibleChange: onVisibleChange
  }, /*#__PURE__*/React.createElement("div", {
    style: {
      position: 'absolute',
      width: 10,
      height: 10,
      background: 'transparent',
      left: -100,
      top: -100,
      zIndex: 999
    },
    ref: menuRef
  })), /*#__PURE__*/React.createElement("div", {
    className: "ra-arch-mimiMap",
    ref: miniMapRef
  }), /*#__PURE__*/React.createElement("div", {
    className: "ra-arch-lane",
    ref: laneRef
  }, /*#__PURE__*/React.createElement("div", {
    ref: containerRef
  }), /*#__PURE__*/React.createElement("svg", {
    width: 30,
    style: {
      left: 0,
      top: 0
    },
    height: "100%",
    ref: laneTitleRef,
    className: "x6-graph-svg",
    xmlns: "http://www.w3.org/2000/svg"
  }, /*#__PURE__*/React.createElement("g", {
    className: "x6-graph-svg-viewport"
  }, /*#__PURE__*/React.createElement("g", {
    className: "x6-graph-svg-stage"
  })))));
};

export default /*#__PURE__*/React.memo(Lane);